/**
 * Copyright Statement:
 * This software and related documentation (ESWIN SOFTWARE) are protected under relevant copyright laws.
 * The information contained herein is confidential and proprietary to
 * Beijing ESWIN Computing Technology Co., Ltd.(ESWIN)and/or its licensors.
 * Without the prior written permission of ESWIN and/or its licensors, any reproduction, modification,
 * use or disclosure Software, and information contained herein, in whole or in part, shall be strictly prohibited.
 *
 * Copyright ©[2023] [Beijing ESWIN Computing Technology Co., Ltd.]. All rights reserved.
 *
 * RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES THAT THE SOFTWARE
 * AND ITS DOCUMENTATIONS (ESWIN SOFTWARE) RECEIVED FROM ESWIN AND / OR ITS REPRESENTATIVES
 * ARE PROVIDED TO RECEIVER ON AN "AS-IS" BASIS ONLY. ESWIN EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON INFRINGEMENT.
 * NEITHER DOES ESWIN PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY
 * WHICH MAY BE USED BY,INCORPORATED IN, OR SUPPLIED WITH THE ESWIN SOFTWARE,
 * AND RECEIVER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL ESWIN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * @file main.c
 * @brief UART echo demo
 * @author abu (abu@eswincomputing.com)
 * @date 2023-02-06
 *
 * @details
 *
 * @platform Fullmask evb board
 *
 * @pins
 * | function name | port number | function number | connector |
 * |:------------- |:------------|:----------------|:----------|
 *      UART2 TX   |    PTA16    |      ALT3       | J8
 *      UART2 RX   |    PTA18    |      ALT3       | J8
 *      PWM2       |    PTB30    |                 | J12-33
 *      EncoderA   |    PTB7     |      ALT3       | J12-16
 *      EncoderB   |    PTB8     |      ALT3       | J12-18
 *      PORTB      |    PTB11    |      ALT1       | J12-22
 *      PORTB      |    PTB13    |      ALT1       | J12-24
 *      PORTB      |    PTB14    |      ALT1       | J12-26
 * @connections(Motor drive board <--> Development board)
 *      E1B             <-->    J12-16
 *      E1A             <-->    J12-18
 *      STBY            <-->    J12-22
 *      AIN1            <-->    J12-24
 *      AIN2            <-->    J12-26
 *      PWMA            <-->    J12-33         PWM2
 *
 *      E2A             <-->    J12-35
 *      E2B             <-->    J12-36
 *      BIN1            <-->    J12-19  Pin49
 *      BIN2            <-->    J12-21  Pin50
 *      PWMB            <-->    J12-31  Pin82  PWM3
 *      J8 VIN+         <-->    J16-1(5V)
 *      J8 VIN-         <-->    J16-3(GND)
 * @connections(Motor drive board <--> Motor drive board)
 *      OUTPUT_IO 5V    <-->    5V
 *      OUTPUT_IO GND   <-->    GND
 * @connections(Motor drive board <--> Motor)
 *      MOTOR_A         <-->    MOTOR
 *蓝牙   RXD                     J10-2
 *蓝牙   TXD                     J10-3
 *舵机   PWM                     J12-7
 * @attention
 * For this example it is necessary to open a terminal emulator and configure it with: \n
 *      TTL RX/TX \n
 *      115200 baud \n
 *      One stop bit \n
 *      No parity \n
 *      No flow control \n
 *      `\n` or `\r` line ending
 *
 * Modification History :
 * Date:               Version:                    Author:
 * Changes:
 *
 */

#include "../board/sdk_project_config.h"
#include "../../peripherals/thirdparty/src/lcd/test.h"
//#include "peripherals_spi_1_config.h"
#include "sdk_project_config.h"
#include "EAM2011_clock.h"
//#include "lcd.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <servo.h>

volatile int g_exitCode = 0;

/** Welcome message displayed at the console */
#define WELCOM_MSG \
    "This example is an simple echo using UART\r\n\
it will send back any character you send to it.\r\n\
The board will greet you if you send 'Hello Board'\r\
\nNow you can begin typing:\r\n"

/** Error message displayed at the console, in case data is received erroneously */
#define ERROR_MSG "An error occurred! The application will stop!\r\n"

/** Timeout in ms for blocking operations */
#define TIMEOUT 500U

/** Receive buffer size */
#define BUFFER_SIZE 256U

/** uart sample */
#define INST_UART_1 (1U)
#define INST_UART_SAMPLE INST_UART_1
#define PPR               13.0 // Encoder pulses per revolution
#define QUADRATURE_FACTOR 1.0  // Frequency doubling factor

/** Buffer used to receive data from the console */
uint8_t g_buffer[BUFFER_SIZE];
uint8_t g_bufferldx;
uint32_t flag;
uint32_t p_flag     = 10;
uint32_t max_speed  = 0;
uint32_t min_speed  = 0;
uint32_t start_flag = 0;

/** uart sample */
//#define INST_UART_SAMPLE INST_UART_2
#define MOTOR_USE_UART2

/* Motor running state definition:
  if define MOTOR_USE_UART2: Motor using uart2,
  else Motor using uppercomputer software. */
#ifdef MOTOR_USE_UART2
#define MortorControl                     "Motor control"
#define MortorStartSuccess                "Motor started successfully"
#define WithoutStartingAgain              "Motor already started"
#define MortorSpeed                       "Motor speed is"
#define WithoutStoppingAgain              "Motor already stopped"
#define MortorStop                        "Motor stopped"
#define MotorNotStarting                  "Please start motor"
#define MotorSpeedMax                     "Motor speed has reached maximum"
#define AccelerationSuccessfulMortorSpeed "Motor acceleration successful, speed is"
#define MotorSpeedMin                     "Motor speed has reached minimum"
#define SlowDownSuccessMortorSpeed        "Motor deceleration successful, speed is"
#define InstructionError                  "Command error, please re-enter"
#else
#define MortorControl                     1  //电机控制
#define MortorStartSuccess                2  //电机启动成功
#define WithoutStartingAgain              3  //电机正在运行无需再次启动
#define MortorSpeed                       4  //电机转速为
#define WithoutStoppingAgain              5  //电机处于停止状态无需再次停止
#define MortorStop                        6  //电机停止
#define MotorNotStarting                  7  //电机未启动请先启动电机
#define MotorSpeedMax                     8  //电机转速达到最大
#define AccelerationSuccessfulMortorSpeed 9  //加速成功，电机转速为
#define MotorSpeedMin                     10 //电机转速达到最小
#define SlowDownSuccessMortorSpeed        11 //减速成功，电机转速为
#define InstructionError                  12 //指令错误请重新输入
#endif

// Define the struct of the motor state and create the struct variables
struct MotorState {
    uint32_t state; // State of motor
    uint32_t speed; // Motor speed
} motor;

// Defines an enumeration of motor command
enum MotorAction {
	START,       /* 0: stop */
	STOP,        /* 1: start */
    LEFT,        /* 2: accelerate */
	RIGHT,       /* 3: decelerate */
	servo,       //4
};

typedef struct {
    uint32_t fifo_empty_cnt;
    uint32_t rov_cnt;
    uint32_t cmp_cnt;
    uint32_t fifo_err_cnt;
} pwm_intr_type_t;

static pwm_intr_type_t g_stPwmCbParam;

static void PwmIntrParamInit(pwm_intr_type_t *param)
{
    param->fifo_empty_cnt = 0;
    param->rov_cnt        = 0;
    param->cmp_cnt        = 0;
    param->fifo_err_cnt   = 0;
}

/**
 * @brief UART rx callback for continuous reception, byte by byte
 *
 * @param  driverState
 * @param  event uart event
 * @param  userData user data
 */
void RxCallback(void *driverState, uart_event_t event, void *userData)  //逐个字节发送，UART1
{
    /* Unused parameters */
    (void)driverState;
    (void)userData;

    /* Check the event type */
    if (event == UART_EVENT_RX_FULL) {
        /* The reception stops when newline is received or the buffer is full */
        if ((g_buffer[g_bufferldx] != '\n') && (g_buffer[g_bufferldx] != '\r') && (g_bufferldx != (BUFFER_SIZE - 2U))) {
            /* Update the buffer index and the rx buffer */
            g_bufferldx++;
            UART_DRV_SetRxBuffer(INST_UART_SAMPLE, &g_buffer[g_bufferldx], 1U);
        } else {
            g_buffer[g_bufferldx++] = '\r';
            g_buffer[g_bufferldx++] = '\n';
            g_buffer[g_bufferldx]   = '\0';
        }
    }
}

int main(void)
{

    /* Write your local variable definition here */
    status_t status;
    /* Declare a buffer used to store the received data */
    uint32_t bytesRemaining;
    supertmr_state_t stSupertmr2StateStruct;
    supertmr_state_t stSupertmr1StateStruct;
//    supertmr_quad_decoder_state_t qd_state;
//    uint32_t pulses_last = 0;
//    uint32_t pulses      = 0;

    /* Write your code here */

    /* Clock Init */
    CLOCK_SYS_Init(g_pstClockManConfigsArr[0]);

    /** Initialize pins
     *    -    See PinSettings component for more info
     */
    PINS_DRV_Init(NUM_OF_CONFIGURED_PINS, g_stPinmuxConfigArr);

    /* Initialize UART instance */
    UART_DRV_Init(INST_UART_SAMPLE, &g_stUartState_1, &g_stUart1UserConfig0);
    //UART_DRV_Init(INST_UART_SAMPLE_2, &g_stUartState_2, &g_stUart2UserConfig0);
    /* Install the callback for rx events */
    UART_DRV_InstallRxCallback(INST_UART_SAMPLE, RxCallback, NULL);

    UART_DRV_SendDataBlocking(INST_UART_SAMPLE, (uint8_t *)WELCOM_MSG, strlen(WELCOM_MSG), TIMEOUT);

    setLogPort(1);

    /* SUPERTMR2 module initialized to process  Quadrature decode */
    SUPERTMR_DRV_Init(INST_SUPERTMR_QD_2, &g_stSupertmr2UserConfigQd, &stSupertmr2StateStruct);
    SUPERTMR_DRV_Init(INST_SUPERTMR_QD_1, &g_stSupertmr1UserConfigQd, &stSupertmr1StateStruct);

    /* SUPERTMR2 module works in Quadrature decode mode */
    SUPERTMR_DRV_QuadDecodeStart(INST_SUPERTMR_QD_2, &g_stSupertmr2QuadDecodeConfig);
    SUPERTMR_DRV_QuadDecodeStart(INST_SUPERTMR_QD_1, &g_stSupertmr1QuadDecodeConfig);
    PwmIntrParamInit(&g_stPwmCbParam);
    /* 开启 FTM0 时钟，使能 PWM0 */

    //舵机PWM初始化
    PWM_DRV_Init(INST_PWM_0, &g_stPwmState_0, &g_stPwm0Config0); //7
	PWM_DRV_Init(INST_PWM_1, &g_stPwmState_1, &g_stPwm1Config0); //32
    PWM_DRV_Init(INST_PWM_4, &g_stPwmState_4, &g_stPwm4Config0);
    //角度更改
	servo_angle(140);
	PWM_DRV_Cfg(INST_PWM_4, &g_stPwmState_4, &g_stPwm4Config0);

    /* Send a welcome message */
#ifdef MOTOR_USE_UART2
    printf("%s\r\n", MortorControl);
#else
    printf(";%d;\r\n", MortorControl);
#endif

    /* Infinite loop:
     *     - Receive data from user
     *     - Echo the received data back
     */

    while (1) {
        /* Receive and store data byte by byte until new line character is received,
         * or the buffer becomes full (256 characters received)
         */
    	//UART_Example();

        UART_DRV_ReceiveData(INST_UART_SAMPLE, g_buffer, 1U);/* Wait for transfer to be completed */
        while (UART_DRV_GetReceiveStatus(INST_UART_SAMPLE, &bytesRemaining) == STATUS_BUSY);/* Check the status */
        status = UART_DRV_GetReceiveStatus(INST_UART_SAMPLE, &bytesRemaining);
        if (status != STATUS_SUCCESS) {/* If an error occurred, send the error message and exit the loop */
            UART_DRV_SendDataBlocking(INST_UART_SAMPLE, (uint8_t *)ERROR_MSG, strlen(ERROR_MSG), TIMEOUT);
            break;}
        g_bufferldx++;
        g_buffer[g_bufferldx] = 0U;

        UART_DRV_SendDataBlocking(INST_UART_SAMPLE, g_buffer, g_bufferldx, TIMEOUT);
        /* Reset the buffer index to start a new reception */
        g_bufferldx = 0U;
        flag = g_buffer[0] - '0';

        //motor
		PINS_DRV_WritePin(PORTB, 11, 1); //tb6612 stby pin set 1
		PINS_DRV_WritePin(PORTB, 13, 0); //ain1 pb13 pb14 is used to control the forward and reverse rotation
		PINS_DRV_WritePin(PORTB, 14, 1); //ain2
		PINS_DRV_WritePin(PORTB, 25, 0); //Bin1 pb13 pb14 is used to control the forward and reverse rotation
		PINS_DRV_WritePin(PORTB, 26, 1); //Bin2

        switch (flag) {
        case START: //0
            PWM_DRV_Init(INST_PWM_0, &g_stPwmState_0, &g_stPwm0Config0); //7
            PWM_DRV_Init(INST_PWM_1, &g_stPwmState_1, &g_stPwm1Config0); //32
            PWM_DRV_Init(INST_PWM_2, &g_stPwmState_2, &g_stPwm2Config0); //31
            PWM_DRV_Init(INST_PWM_3, &g_stPwmState_3, &g_stPwm3Config0); //33
            PWM_DRV_Init(INST_PWM_4, &g_stPwmState_4, &g_stPwm4Config0); //40

            g_stPwm0Config0.duty = 0x0100;
            g_stPwm1Config0.duty = 0x0200;
        	g_stPwm2Config0.duty = 0x0400;
			g_stPwm3Config0.duty = 0x0800;
			g_stPwm4Config0.duty = 0x2000;

			//g_stPwm0Config0.frequency = 50; // 必须显式设置
			PWM_DRV_Cfg(INST_PWM_0, &g_stPwmState_0, &g_stPwm0Config0);
			PWM_DRV_Cfg(INST_PWM_1, &g_stPwmState_1, &g_stPwm1Config0);
			PWM_DRV_Cfg(INST_PWM_2, &g_stPwmState_2, &g_stPwm2Config0);
			PWM_DRV_Cfg(INST_PWM_3, &g_stPwmState_3, &g_stPwm3Config0);
			PWM_DRV_Cfg(INST_PWM_4, &g_stPwmState_4, &g_stPwm4Config0);

			break;

		case STOP:  //1
			PINS_DRV_WritePin(PORTB, 11, 0); //tb6612 stby pin set 0
			PINS_DRV_WritePin(PORTB, 13, 0); //ain1 pb13 pb14 is used to control the forward and reverse rotation
			PINS_DRV_WritePin(PORTB, 14, 0); //ain2
			PINS_DRV_WritePin(PORTB, 25, 0); //Bin1 pb13 pb14 is used to control the forward and reverse rotation
			PINS_DRV_WritePin(PORTB, 26, 0); //Bin2
			PINS_DRV_WritePin(PORTA, 6, 0); //舵机
			PWM_DRV_Deinit(INST_PWM_0);
			PWM_DRV_Deinit(INST_PWM_1);
			PWM_DRV_Deinit(INST_PWM_2);
			PWM_DRV_Deinit(INST_PWM_3);
			PWM_DRV_Deinit(INST_PWM_4);
			break;

		case LEFT:  //2
			g_stPwm2Config0.duty = 0x2800;
			g_stPwm3Config0.duty = 0x2000;
			PWM_DRV_Cfg(INST_PWM_2, &g_stPwmState_2, &g_stPwm2Config0);
			PWM_DRV_Cfg(INST_PWM_3, &g_stPwmState_3, &g_stPwm3Config0);
			break;

		case RIGHT:  //3
			g_stPwm2Config0.duty = 0x2000;
			g_stPwm3Config0.duty = 0x2800;
			PWM_DRV_Cfg(INST_PWM_2, &g_stPwmState_2, &g_stPwm2Config0);
			PWM_DRV_Cfg(INST_PWM_3, &g_stPwmState_3, &g_stPwm3Config0);
			break;

		case servo:  //4
			g_stPwm0Config0.duty = 0x2000;
			PWM_DRV_Cfg(INST_PWM_0, &g_stPwmState_0, &g_stPwm0Config0);
			break;
        }
        /* Reset the buffer index to start a new reception */
        g_bufferldx = 0U;

        //舵机代码

    }
    return 0;
}
